# -*- coding:utf-8 -*-

"""订单接口"""
import logging
from datetime import datetime
from flask import g
from flask import jsonify
from flask import request
from ihome import db, redis_store
from ihome.models import House
from ihome.models import User
from ihome.models import Order
from ihome.api_1_0 import api
from ihome.utils.response_code import RET
from ihome.utils.common import login_required


# 保存订单
@api.route('/orders', methods=["POST"])
@login_required
def save_order():
    """保存用户提交的订单"""
    # 一 获取参数
    # 获取用户id
    user_id = g.user_id

    # 获取其他参数
    order_data = request.get_json()
    if not order_data:
        return jsonify(errno=RET.PARAMERR, errmsg="1订单提交 获取参数错误 ")

    # 房屋id
    house_id = order_data.get("house_id")
    # 入住日期
    start_date_str = order_data.get('start_date')
    # 退房日期
    end_date_str = order_data.get('end_date')

    # 二 校验参数
    # 2.1 参数的完整性校验
    if not all([house_id, start_date_str, end_date_str]):
        return jsonify(errno=RET.PARAMERR, errmsg="2订单提交 参数不完整")

    # 2.2 对日期进行格式化
    start_date = None
    end_date = None
    try:
        start_date = datetime.strptime(start_date_str, '%Y-%m-%d')
        end_date = datetime.strptime(end_date_str, '%Y-%m-%d')

        if start_date and end_date:
            assert start_date <= end_date, '提交订单 入住日期必须小于退房日期'

        days = (end_date - start_date).days + 1
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.PARAMERR, errmsg="3提交订单 提交的日期数据不正确")

    # 三 逻辑处理
    # 3.1 查询房屋是否存在
    try:
        house = House.query.get(house_id)
    except Exception as e:
        logging(e)
        return jsonify(errno=RET.DBERR, errmsg='1订单提交 Mysql查询房间时出现异常')

    if not house:
        return jsonify(errno=RET.NODATA, errmsg='订单提交 指定的房间不存在')

    # 3.2 判断用户是否为房东
    if user_id == house.user_id:
        return jsonify(errno=RET.ROLEERR, errmsg='订单提交 不能预定自己的房屋')

    # 3.3 查询是否被别人预定
    try:
        count = Order.query.filter(
            Order.house_id == house_id, Order.begin_date <= end_date, Order.end_date >= start_date).count()
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='2订单提交 Mysql查询房间时间冲突数据出现异常')

    # 校验结果
    if count > 0:
        return jsonify(errno=RET.DATAERR, errmsg='订单提交 房屋已经被预定')

    # 3.4 计算总价
    amount = days * house.price
    # 生成模型队形,保存订单基本信息:房屋/用户/订单的开始日期/订单的结束日期/天数/价格/总价
    order = Order()
    order.house_id = house_id
    order.user_id = user_id,
    order.begin_date = start_date,
    order.end_date = end_date
    order.days = days
    order.house_price = house.price
    order.amount = amount

    # 3.5 保存订单数据到数据酷
    try:
        db.session.add(order)
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='3 订单提交 MySQL保存订单信息时报错')

    # 3.5 保存订单数据到数据库

    # 四 返回结果
    # 前端对应服务器的操作如果更新资源或者新建资源,可以返回对应的信息
    return jsonify(errno=RET.OK, errmsg='订单提交成功', data={"order_id": order.id})


# 查看订单
@api.route('/users/orders')
@login_required
def get_user_orders():
    """查询用户的订单信息"""
    # 一 获取参数
    # 用户id
    user_id = g.user_id
    # 订单类类型 custom(房客)，landlord(房东)
    role = request.args.get('role', "")

    # 二 参数校验

    # 三 逻辑处理
    # 2.1 查询订单数据
    try:
        if role == "landlord":
            # 以房东的身份查询订单
            # 先查询属于自己的房子有哪些
            houses = House.query.filter(House.user_id == user_id).all()
            houses_ids = [house.id for house in houses]
            # 在查询预定了自定房子的订单,默认按照房屋订单发布时间进行倒叙排序
            orders = Order.query.filter(Order.house_id.in_(houses_ids)).order_by(Order.create_time.desc()).all()
        else:
            # 以房客的身份查询订单,查询自己预定的订单
            orders = Order.query.filter(Order.user_id == user_id).order_by(Order.create_time.desc()).all()
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg="获取订单 Mysql在获取订单时,出现异常")

    # 2.2 将订单转换为字典数据
    order_dict_list = []

    if orders:
        for order in orders:
            order_dict_list.append(order.to_dict())

    # 四 返回结果
    return jsonify(errno=RET.OK, errmsg='获取订单成功', data={"orders": order_dict_list})


# 接单和拒单
@api.route('/orders/<int:order_id>/status', methods=["PUT"])
@login_required
def accept_reject_order(order_id):
    """接单/拒单"""
    # 一 获取数据
    # 获取用户信息
    user_id = g.user_id

    # 获取参数,校验参数存在
    req_data = request.get_json()
    if not req_data:
        return jsonify(errno=RET.PARAMERR, errmsg='订单状态变更 参数错误')

    # action参数表明客户端请求的是接单还是拒单的请求
    action = req_data.get('action')

    # 二 校验完整性
    if action not in ('accept', 'reject'):
        return jsonify(errno=RET.PARAMERR, errmsg="2订单状态变更 参数错误")

    # 三 业务逻辑处理
    # 3.1 获取订单的状态信息
    try:
        order = Order.query.filter(Order.id == order_id, Order.status == "WAIT_ACCEPT").first()
        house = order.house
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg='3订单状态变更 Mysql查询订单信息时报错')

    # 3.2 确保房东只能修改属于自己的房子的订单
    if not order or house.user_id != user_id:
        return jsonify(errno=RET.REQERR, errmsg='4订单状态变更 操作无效')

    # 3.3 对接单或拒单分别处理
    # 如果房东选择接单操作
    if action == "accept":
        # 接单,将订单状态设置为等待评论
        order.status = "WAIT_COMMENT"
    elif action == "reject":
        # 如果房东选择拒单操作,需要填写原因
        # 拒单,要求用户传递拒单原因
        reason = req_data.get('reason')
        # 判断房东是否填写拒单原因
        if not reason:
            return jsonify(errno=RET.PARAMERR, errmsg='5订单状态变更时 拒单原因缺失')

        # 如果房东选择拒单,把拒单原因存储到数据库
        order.status = 'REJECTED'
        # comment字段保存拒单原因
        order.comment = reason

    # 3.4 把接单或拒单操作存储数据库
    try:
        db.session.add(order)
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='6订单状态变更时 订单状态变更时,mysql报错')

    # 四 返回结果
    return jsonify(errno=RET.OK, errmsg="7订单状态变更成功")


# 评论订单
@api.route('/orders/<int:order_id>/comment', methods=['PUT'])
@login_required
def save_order_comment(order_id):
    """保存订单评论信息"""
    # 一 获取参数
    user_id = g.user_id
    # 获取参数
    req_data = request.get_json()
    if req_data is None:
        return jsonify(errno=RET.PARAMERR, errmsg="评论订单 参数获取错误")
    # 获取评论内容
    comment = req_data.get("comment")

    # 二 校验参数
    # 要求用户必须要填写内容
    if comment is None:
        return jsonify(errno=RET.PARAMERR, errmsg="评论订单 评论内容为空")

    # 三 业务逻辑处理
    # 3.1 查询订单状态为待评价
    try:
        # 根据订单id/订单所属用户/订单状态为代评价状态
        order = Order.query.filter(Order.id == order_id, Order.user_id == user_id,
                                   Order.status == "WAIT_COMMENT").first()
        # 查询订单涉及到房屋
        house = order.house
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg="评论订单 mysql查询订单信息时出现异常")

    if not order:
        return jsonify(errno=RET.NODATA, errmsg="评论订单 为查找到符合条件的订单")

    # 3.2 保存评价信息
    try:
        # 将订单的状态设置位已完成
        order.status = 'COMPLETE'
        # 保存订单的评论
        order.comment = comment
        # 讲房屋完成的订单数增加1,如果订单已评价,让房屋成交量+1
        house.order_count += 1
        # add_all 可以一次性天骄多条数据,db.session.add_all([order,house])
        db.session.add_all([order, house])
        db.session.commit()
    except Exception as e:
        logging.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='评论订单 订单/房屋信息提交时,报错')

    # 3.2 缓存中存储房屋信息,因为订单成交,导致缓存中的数据已经过期,所以,需要删除过期数据
    try:
        redis_store.delete('house_info_%s' % house.id)
    except Exception as e:
        logging.error(e)
        return jsonify(errno=RET.DBERR, errmsg="订单评论 删除过期房屋信息时,redis出现异常")

    # 四 返回数据
    return jsonify(errno=RET.OK, errmsg="订单的评价信息更新成功")
